using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text;

namespace Quiki
{
    [SuppressMessage ("Microsoft.Design", "CA1036:OverrideMethodsOnComparableTypes")]
    public class WikiDocReference : IComparable<WikiDocReference>
    {
        public const string CategoryText = "Category";

        public WikiDocReference()
        {
        }

        public WikiDocReference(string value)
        {
            string[] splits = value.Split(':');
            parts = new List<string>();

            foreach (string split in splits)
                parts.Add(split.Trim());
        }

        public string FirstPart
        {
            get
            {
                return parts[0];
            }
        }

        public bool HasExplicitNamespace
        {
            get
            {
                return parts.Count > 1;
            }
        }

        public bool IsCategory
        {
            get
            {
                return FirstPart == CategoryText;
            }
        }

        public string LastPart
        {
            get
            {
                return parts[parts.Count - 1];
            }
        }

        public IList<string> Parts
        {
            get { return parts; }
        }

        public int CompareTo(WikiDocReference other)
        {
            string name1 = ToString();
            string name2 = other.ToString();

            return String.Compare(name1, name2, StringComparison.OrdinalIgnoreCase);
        }

        [SuppressMessage ("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
        public override bool Equals (object obj)
        {
            if (obj == null || !(obj is WikiDocReference))
                return false;

            WikiDocReference that = (WikiDocReference) obj;

            if (parts.Count != that.parts.Count)
                return false;

            for (int i = 0; i < parts.Count; i++)
            {
                if (0 != String.Compare (parts[i], that.parts[i], StringComparison.Ordinal))
                    return false;
            }

            return true;
        }

        public override int GetHashCode()
        {
            int hashCode = 1;

            for (int i = 0; i < parts.Count; i++)
                hashCode ^= parts[i].GetHashCode();

            return hashCode;
        }

        public void InsertPartAtFront(string part)
        {
            parts.Insert(0, part);
        }

        public string NamespaceToString ()
        {
            return ToString (false);
        }

        public override string ToString ()
        {
            return ToString(true);
        }

        [SuppressMessage ("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings")]
        public string ToUrl ()
        {
            StringBuilder url = new StringBuilder ();

            for (int i = 0; i < parts.Count - 1; i++)
                url.AppendFormat ("{0}/", parts[i]);

            url.AppendFormat ("{0}.html", LastPart.Replace (' ', '_'));

            return url.ToString();
        }

        private string ToString(bool includeDocumentName)
        {
            StringBuilder value = new StringBuilder();
            for (int i = 0; i < (includeDocumentName ? parts.Count : parts.Count - 1); i++)
            {
                string part = parts[i];

                if (value.Length > 0)
                    value.Append(':');
                value.Append(part);
            }

            return value.ToString();
        }

        private List<string> parts = new List<string>();
    }
}